/**
 * WebSocket类
 */
export class CWebSocket {
    private ws: WebSocket
    onConnect: (event: Event) => void
    onMessage: (data: unknown) => void
    onError: (event: Event) => any
    onClose: (event: CloseEvent) => any

    constructor() {
        this.ws = null
        /** 事件 */
        this.onConnect = null
        this.onMessage = null
        this.onError = null
        this.onClose = null
    }

    /** 连接网络 */
    connect(option: string | { protocol: string, ip: string, port: string }): boolean {
        var _this = this
        if (this.ws && this.ws.readyState === WebSocket.CONNECTING) {
            cc.log("已经连接上网络, 重新连接前请先调用close方法!")
            return false
        }
        var url = ""
        if (typeof option == "string") {
            url = option
        } else {
            url = option.protocol + "://" + option.ip + ":" + option.port
        }
        let initWs = () => {
            this.ws.binaryType = "arraybuffer"
            this.ws.onopen = this.onConnect
            this.ws.onmessage = function (event) {
                _this.onMessage(event.data)
            };
            this.ws.onclose = this.onClose
            this.ws.onerror = this.onError
        }
        if (cc.sys.isNative) {
            cc.resources.load(`ssl/cacert`, (err, pem: cc.Asset) => {
                if (err) {
                    cc.error(err)
                    cc.resources.load(`cacert`, (err, pem: cc.Asset) => {
                        if (err) {
                            cc.error(err)
                        } else {
                            cc.log(pem.nativeUrl)
                            this.ws = new (<any>WebSocket)(url, null, pem.nativeUrl)
                            initWs()
                        }
                    })
                } else {
                    cc.log(pem.nativeUrl)
                    this.ws = new (<any>WebSocket)(url, null, pem.nativeUrl)
                    initWs()
                }
            })
        } else {
            this.ws = new WebSocket(url)
            initWs()
        }

        return true
    }


    /**
     * @method send 发送消息
     * @param data 
     */
    send(data: string | ArrayBufferLike | Blob | ArrayBufferView): boolean {

        if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
            cc.log('CWebSocket send', '网络连接已关闭, 发送消息失败')
            return false
        }

        if (data instanceof String || data instanceof ArrayBuffer) {

            this.ws.send(data)

            return true
        } else {
            cc.log('CWebSocket send', `不支持的数据类型${typeof data}`)
        }

        return false

    }

    /** 主动关闭连接 */
    close(): boolean {
        if (this.ws && this.ws.readyState !== WebSocket.CLOSED) {
            this.ws.close()
            this.ws = null
        }
        return true
    }

    getReadyState(): number {
        if (this.ws) {
            return this.ws.readyState
        }
        return WebSocket.CLOSED
    }
}
